#include "ThreadPool.h"
#include <iostream>

ThreadPool::ThreadPool() {}

void ThreadPool::setMode(PoolMode mode) { this->poolMode_ = mode; }

void ThreadPool::setTaskQueMaxThreshold(size_t threshold) {
  this->taskQueThreshHold_ = threshold;
}

// 任务生产者
void ThreadPool::submitTask(std::shared_ptr<Task> Tasksptr) {
  // 获取锁
  std::unique_lock<std::mutex> lock(taskQueMtx_);
  // 线程通信
  if (!notFull_.wait_for(lock, std::chrono::seconds(1), [&]() {
    return taskQue_.size() < taskQueThreshHold_;
  })) {
    // 超时仍未满足条件，返回失败
    std::cerr << "task queue is full, submit task fail.\n";
    return;
  }

  // 队列有空, 任务放入队列
  taskQue_.emplace(Tasksptr);
  taskSize_++;
  // 队列不空了, 通知消费者
  notEmpty_.notify_one();
};

void ThreadPool::start(size_t initThreadSize) {
  this->initThreadSize_ = initThreadSize;

  for (int i = 0; i < initThreadSize_; i++) {
    auto t_ptr = std::make_unique<Thread>([this] {
      threadFunc();
    });
    threads_.emplace_back(std::move(t_ptr));
  }

  for (int i = 0; i < initThreadSize_; i++) {
    threads_[i]->start();
  }
}

// 消费者
void ThreadPool::threadFunc() {

  for (;;) {
    std::shared_ptr<Task> task;
    { 
      // 获取锁
      std::unique_lock<std::mutex> lock(taskQueMtx_);
      std::cout << __PRETTY_FUNCTION__ << " tid:" << std::this_thread::get_id() << "\n";
      
      // 等待notEmpty
      notEmpty_.wait(lock, [&]() {return taskQue_.size() > 0;});
      // 取任务
      task = taskQue_.front();
      taskQue_.pop();
      taskSize_--;

      // 队列还有任务, 通知其他消费者
      if (taskQue_.size() > 0) {
        notEmpty_.notify_all();
      }

      // 通知生产者, 提交任务
      notFull_.notify_all();
    } // 释放锁

    // 线程执行任务
    if (task != nullptr) {
      task->run();
    }
  }
}